package com.example.high_slope_electronic_sand_table.environment.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.example.high_slope_electronic_sand_table.common.constant.DataClassificationConstant;
import com.example.high_slope_electronic_sand_table.common.constant.GeneralConstants;
import com.example.high_slope_electronic_sand_table.common.util.WeightRandomUtil;
import com.example.high_slope_electronic_sand_table.environment.Enum.HumidityWarningEnum;
import com.example.high_slope_electronic_sand_table.environment.Enum.SpeedWarningEnum;
import com.example.high_slope_electronic_sand_table.environment.Enum.TemperatureWarningEnum;
import com.example.high_slope_electronic_sand_table.environment.dto.EnvironmentMonitorDTO;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class EnvironmentMonitorService {

    private final static String DEVICE_SN_MIDDLE= "0EMD0"; // 设备编码中段

    private final static Integer MAX_SIZE = 30; // 最大数据条数

    private static Map<String, List<EnvironmentMonitorDTO>> environmentMonitorDataMap = new HashMap<>();


    /**
     * 查询单条环境监测数据
     *
     * @return
     */
    public EnvironmentMonitorDTO getCurrentMonitorData(String deviceId) {
        if (!environmentMonitorDataMap.containsKey(deviceId) || environmentMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        // 获取当前的时间和当前设备数据最后一条时间比较，如果当前时间比数据最后一条时间大于等于10分钟，则重新生成一条数据放在列表最后。如果小于十分钟，返回最后一条数据
        LocalDateTime currentDateTime = LocalDateTime.now();
        EnvironmentMonitorDTO lastEnvironmentMonitorDTO = environmentMonitorDataMap.get(deviceId).get(MAX_SIZE - 1);
        LocalDateTime lastDateTime = LocalDateTime.parse(lastEnvironmentMonitorDTO.getDatetime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
        Duration duration = Duration.between(lastDateTime, currentDateTime);
        if (duration.toMinutes() >= GeneralConstants.GENERATOR_DATA_DURATION_TIME) {
            for (int item = 1; item <= duration.toMinutes() / GeneralConstants.GENERATOR_DATA_DURATION_TIME; item++) {
                Date newDate = DateUtil.offset(Date.from(lastDateTime.atZone(ZoneId.systemDefault()).toInstant()), DateField.MINUTE, +item * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 最后一条时间向后推10分钟
                environmentMonitorDataMap.get(deviceId).add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
                environmentMonitorDataMap.get(deviceId).remove(0);
            }
            return environmentMonitorDataMap.get(deviceId).get(MAX_SIZE - 1);
        } else {
            return lastEnvironmentMonitorDTO;
        }
    }

    /**
     * 查询某个设备所有环境监测数据
     *
     * @return
     */
    public List<EnvironmentMonitorDTO> listMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!environmentMonitorDataMap.containsKey(deviceId) || environmentMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return environmentMonitorDataMap.get(deviceId).stream().sorted(Comparator.comparing(EnvironmentMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 查询某个设备所有环境监测告警数据
     *
     * @return
     */
    public List<EnvironmentMonitorDTO> listWarningMonitorDataByDeviceId(@PathVariable String deviceId) {
        if (!environmentMonitorDataMap.containsKey(deviceId) || environmentMonitorDataMap.get(deviceId).isEmpty()) {
            batchGeneratorMonitorDataS(deviceId);
        }
        return environmentMonitorDataMap.get(deviceId).stream()
                .sorted(Comparator.comparing(EnvironmentMonitorDTO::getDatetime).reversed())
                .filter(environmentMonitorDTO -> environmentMonitorDTO.getTemperatureWarningLevel() != 0
                        || environmentMonitorDTO.getHumidityWarningLevel() != 0
                        || environmentMonitorDTO.getSpeedWarningLevel() != 0)
                .collect(Collectors.toList());
    }

    /**
     * 查询多条环境监测数据
     *
     * @return
     */
    public List<EnvironmentMonitorDTO> listMonitorData() {
        List<EnvironmentMonitorDTO> environmentMonitorDTOS = new ArrayList<>();
        if (environmentMonitorDataMap.isEmpty()){
            // 生成3个设备相关数据
            for (int index = 0; index < GeneralConstants.GENERATOR_DEVICE_NUMBER ; index ++){
                String deviceId = GeneralConstants.DEVICE_SN_PREFIX + DEVICE_SN_MIDDLE + index;
                batchGeneratorMonitorDataS(deviceId);
            }
        }
        for (String deviceId : environmentMonitorDataMap.keySet()) {
            environmentMonitorDTOS.addAll(environmentMonitorDataMap.get(deviceId));
        }
        return environmentMonitorDTOS.stream().sorted(Comparator.comparing(EnvironmentMonitorDTO::getDatetime).reversed()).collect(Collectors.toList());
    }

    /**
     * 批量生成环境监测数据
     *
     * @param deviceId
     */
    private void batchGeneratorMonitorDataS(String deviceId) {
        List<EnvironmentMonitorDTO> environmentMonitorDTOS = new ArrayList<>(MAX_SIZE);
        for (int item = 1; item <= MAX_SIZE; item++) {
            Date date = DateUtil.date();
            Date newDate = DateUtil.offset(date, DateField.MINUTE, -(MAX_SIZE - item) * GeneralConstants.GENERATOR_DATA_DURATION_TIME); // 当前时间向前推item*10分钟
            environmentMonitorDTOS.add(generatorMonitorData(deviceId, DateUtil.format(newDate, DatePattern.NORM_DATETIME_PATTERN)));
        }
        environmentMonitorDataMap.put(deviceId, environmentMonitorDTOS);
    }

    /**
     * 生成环境监测数据
     *
     * @param deviceId
     * @param dateTime
     * @return
     */
    private EnvironmentMonitorDTO generatorMonitorData(String deviceId, String dateTime){
        EnvironmentMonitorDTO environmentMonitorDTO = new EnvironmentMonitorDTO();
        environmentMonitorDTO.setDeviceId(deviceId);
        // 生成权重随机数
        Float temperatureValue = WeightRandomUtil.getWeightRandomValue(TemperatureWarningEnum.WARNING_ONE.getValue(),
                TemperatureWarningEnum.WARNING_TWO.getValue(), TemperatureWarningEnum.WARNING_THREE.getValue(),
                -15f, 60f);
        environmentMonitorDTO.setTemperature(temperatureValue);
        Float humidityValue = WeightRandomUtil.getWeightRandomValue(HumidityWarningEnum.WARNING_ONE.getValue(),
                HumidityWarningEnum.WARNING_TWO.getValue(), HumidityWarningEnum.WARNING_THREE.getValue(),
                12f, 99f);
        environmentMonitorDTO.setHumidity(humidityValue);
        Float speedValue = WeightRandomUtil.getWeightRandomValue(SpeedWarningEnum.WARNING_ONE.getValue(),
                SpeedWarningEnum.WARNING_TWO.getValue(), SpeedWarningEnum.WARNING_THREE.getValue(),
                0f, 36.9f);
        environmentMonitorDTO.setSpeed(speedValue);
//        environmentMonitorDTO.setTemperature(RandomUtil.randomFloat(-15f, 60f));
//        environmentMonitorDTO.setHumidity(RandomUtil.randomFloat(12f, 99f));
//        environmentMonitorDTO.setSpeed(RandomUtil.randomFloat(0f, 36.9f));
        environmentMonitorDTO.setDatetime(dateTime);
        checkWarningLevel(environmentMonitorDTO);
        return environmentMonitorDTO;
    }

    /**
     * 判断告警等级
     *
     * @param environmentMonitorDTO
     */
    private void checkWarningLevel(EnvironmentMonitorDTO environmentMonitorDTO) {
        // 温度
        Optional<TemperatureWarningEnum> temperatureFirst = DataClassificationConstant.temperatureWarningList.stream()
                .filter(temperatureWarning -> environmentMonitorDTO.getTemperature() >= temperatureWarning.getValue())
                .findFirst();
        environmentMonitorDTO.setTemperatureWarningLevel(
                temperatureFirst.isEmpty() || ObjectUtil.isEmpty(temperatureFirst.get()) ? 0 : temperatureFirst.get().getWarningLevel());
        // 湿度
        Optional<HumidityWarningEnum> humidityFirst = DataClassificationConstant.humidityWarningList.stream()
                .filter(humidityWarning -> environmentMonitorDTO.getHumidity() >= humidityWarning.getValue())
                .findFirst();
        environmentMonitorDTO.setHumidityWarningLevel(
                humidityFirst.isEmpty() || ObjectUtil.isEmpty(humidityFirst.get()) ? 0 : humidityFirst.get().getWarningLevel());
        // 风速
        Optional<SpeedWarningEnum> speedFirst = DataClassificationConstant.speedWarningList.stream()
                .filter(speedWarning -> environmentMonitorDTO.getSpeed() >= speedWarning.getValue())
                .findFirst();
        environmentMonitorDTO.setSpeedWarningLevel(
                speedFirst.isEmpty() || ObjectUtil.isEmpty(speedFirst.get()) ? 0 : speedFirst.get().getWarningLevel());
    }
}
